import json

import requests
from openai import OpenAI


#获取天气相关函数
def get_weather(city):
    '''
    查询即时天气函数
    param loc：必要参数，字符串类型，用于表示查询天气的具体城市名称，\
    注意，中国的城市需要用对应城市的英文名称代替，例如如果需要查询北京市天气，则loc参数需要输入'Beijing'；
    ：return：Openweather API查询即时天气的结果，具体URL请求地址为：https://api.openweathermap.org/data/2.5/weather\
    返回结果对象类型为解析之后的JSON格式对象，并用字符串形式进行表示，其中包含了全部重要的天气信
    :return:
    '''
    weather_api_key = '9e7d36701fac2b6f3da5546a76661377'

    param = {
        'q': city,
        'units': 'metric',
        'appid': weather_api_key,
        "lang":"zh_cn"
    }

    url = "https://api.openweathermap.org/data/2.5/weather"

    response = requests.get(url=url, params=param)
    data = response.json()

    #正常返回值
    return json.dumps(data)
    #异常返回值
    #return "对不起，由于网络问题无法查询此城市的天气情况"

get_weather_description = "这是一个查询某个城市天气的函数"

get_weather_function = {
    "name": "get_weather",
    "description": get_weather_description,
    "parameters": {
        "type": "object",
        "properties": {
            "city": {
                "type": "string",
                "description": "城市名称，如果不是英文需要转为英文，如北京则输入beijing"
            }
        },
        "required": ["city"]
    }
}


#Function Calling实现类

def run_conv(client,
             model,
             messages,
             tools=None,
             functions_list=None):
    """
    能够自动执行外部函数调用的Chat对话模型
    :param messages: 必要参数，输入到Chat模型的messages参数对象
    :param api_key: 必要参数，调用模型的API-KEY
    :param tools: 可选参数，默认为None，可以设置为包含全部外部函数的列表对象
    :param model: Chat模型，可选参数，默认模型为deepseek-chat
    :return：Chat模型输出结果
    """
    user_messages = messages

    # 如果没有外部函数库，则执行普通的对话任务
    if tools == None:
        response = client.chat.completions.create(
            model=model,
            messages=user_messages
        )
        final_response = response.choices[0].message.content

    # 若存在外部函数库，则需要灵活选取外部函数并进行回答
    else:
        # 创建外部函数库字典
        available_functions = {func.__name__: func for func in functions_list}

        # 创建包含用户问题的message
        messages = user_messages

        # first response
        response = client.chat.completions.create(
            model=model,
            messages=user_messages,
            tools=tools,
        )
        response_message = response.choices[0].message

        # 判断是否需要调用外部函数
        if response_message.tool_calls == None:
            final_response = response_message.content
        else:
            # 获取函数名
            function_name = response_message.tool_calls[0].function.name
            # 获取函数对象
            fuction_to_call = available_functions[function_name]
            # 获取函数参数
            function_args = json.loads(response_message.tool_calls[0].function.arguments)

            # 将函数参数输入到函数中，获取函数计算结果
            function_response = fuction_to_call(**function_args)

            # messages中拼接first response消息
            user_messages.append(response_message.model_dump())

            # messages中拼接外部函数输出结果
            user_messages.append(
                {
                    "role": "tool",
                    "content": function_response,
                    "tool_call_id": response_message.tool_calls[0].id
                }
            )

            # 第二次调用模型
            second_response = client.chat.completions.create(
                model=model,
                messages=user_messages)

            # 获取最终结果
            final_response = second_response.choices[0].message.content

    return final_response